package com.mikufufu.blog.utils;

import org.jetbrains.annotations.NotNull;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.core.env.Environment;
import org.springframework.stereotype.Component;

import java.lang.annotation.Annotation;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.Date;
import java.util.Map;

/**
 * 这个类用于提供一个全局的获取Spring ApplicationContext的方法
 * 
 */
@Component  // 标记为Spring组件
public class SpringUtils implements ApplicationContextAware {

    // 静态的ApplicationContext引用
    private static ApplicationContext context;

    // 提供一个全局的获取ApplicationContext的方法
    public static ApplicationContext getApplicationContext() {
        return context == null ? null : context;
    }

    // 实现ApplicationContextAware接口的方法，Spring会自动调用这个方法，传入ApplicationContext
    @Override
    public void setApplicationContext(@NotNull ApplicationContext applicationContext) throws BeansException {
        // 将ApplicationContext保存到静态变量中
        context = applicationContext;
    }

    /**
     * 根据bean的class获取bean
     * @param clazz bean的class
     * @return bean
     */
    public static <T> T getBean(Class<T> clazz) {
        return clazz == null ? null : context.getBean(clazz);
    }

    /**
     * 根据bean的id获取bean
     * @param beanId bean的id
     * @return bean
     */
    public static Object getBean(String beanId) {
        return beanId == null ? null : context.getBean(beanId);
    }

    /**
     * 根据bean的id和class获取bean
     * @param beanName bean的id
     * @param clazz bean的class
     * @return bean
     */
    public static <T> T getBean(String beanName, Class<T> clazz) {
        if (null != beanName && !beanName.trim().isEmpty()) {
            return clazz == null ? null : context.getBean(beanName, clazz);
        } else {
            return null;
        }
    }

    /**
     * 获取包含指定注解的所有Bean的映射。
     *
     * @param clazz 指定的注解类，用于查询包含该注解的所有Bean。
     * @return 返回一个映射，其中键是Bean的名称，值是Bean的实例。如果指定的注解类为null，则返回null。
     */
    public static Map<String, Object> getBeansWithAnnotation(Class<? extends Annotation> clazz) {
        // 判断注解类是否为null，为null则直接返回null，否则查询并返回包含该注解的所有Bean
        return clazz == null ? null : context.getBeansWithAnnotation(clazz);
    }

    /**
     * 获取所有实现指定接口的Bean的映射。
     *
     * @param clazz 指定的接口类，用于查询实现该接口的所有Bean。
     * @return 返回一个映射，其中键是Bean的名称，值是Bean的实例。如果指定的接口类为null，则返回null。
     */
    public static <T> Map<String,T> getImplementations(Class<T> clazz) {
        return context.getBeansOfType(clazz);
    }

    /**
     * 获取当前环境
     * @return 当前环境
     */
    public static String getActiveProfile() {
        return context.getEnvironment().getActiveProfiles()[0];
    }

    /**
     * 获取当前属性名对应的属性值
     * @param key 属性名
     * @return 属性值
     */
    public static String getProperty(String key) {
        return context.getEnvironment().getProperty(key);
    }

    /**
     * 获取当前的环境对象。
     *
     * @return Environment 返回当前的环境对象，该对象包含了系统的环境配置信息。
     */
    public static Environment getEnvironment() {
        // 从上下文中获取环境对象
        return context.getEnvironment();
    }


    /**
     * 获取当前环境的ip
     * @return 当前ip
     */
    public static String getHost(){
        try {
            return InetAddress.getLocalHost().getHostAddress() + ":" + getProperty("server.port");
        } catch (UnknownHostException e) {
            throw new RuntimeException("获取当前环境的ip失败");
        }
    }

    /**
     * 获取系统启动时间
     * @return 返回系统启动的时间戳，单位为毫秒。
     */
    public static Date getStartupTime() {
        return new Date(context.getStartupDate());
    }

}
